#ifndef FIXED_H
#define FIXED_H
#include<stdint.h>

template<int fracbits>
class fixed
{
  private:
    int32_t value;

    int32_t multiply(int32_t a, int32_t b) const {
      int64_t tmp = (int64_t)a * (int64_t)b + (1 << (fracbits - 1));
      tmp >>= fracbits;
      return tmp;
    }
#if 0
    int32_t multiply(int32_t a, int32_t b) const {
      return (a >> (fracbits/2)) * (b >> (fracbits/2));
    }
#endif 

    int32_t divide(int32_t a, int32_t b) const {
      int64_t tmp = a;
      tmp <<= fracbits;
      tmp += (b >> 1);
      tmp /= b;
      return tmp;
    }

  public:
    fixed()
    { value = 0; }

    fixed(int i)
    { value = i << fracbits; }

    fixed(float i)
    { value = (int32_t)(i * (1 << fracbits)); }

    fixed(const fixed& other)
    { value = other.value; }

    fixed operator+(const fixed& other) const
    {
      fixed res;
      res.value = value + other.value;
      return res;
    }

    fixed& operator+=(const fixed& other)
    {
      value += other.value;
      return *this;
    }

    fixed operator-() const
    {
      fixed res;
      res.value = -value;
      return res;
    }

    fixed operator-(const fixed& other) const
    {
      fixed res;
      res.value = value - other.value;
      return res;
    }

    fixed operator-=(const fixed& other)
    {
      value -= other.value;
      return *this;
    }

    fixed operator*(const fixed& other) const
    {
      fixed res;
      res.value = multiply(value,other.value);
      return res;
    }

    fixed& operator*=(const fixed& other)
    {
      value = multiply(value,other.value);
      return *this;
    }

    fixed operator/(const fixed& other) const
    {
      fixed res;
      res.value = divide(value,other.value);
      return res;
    }

    fixed& operator/=(const fixed& other)
    {
      value = divide(value,other.value);
      return *this;
    }

    fixed& operator=(const fixed& other)
    {
      value = other.value;
      return *this;
    }

    fixed& operator=(const float& other)
    {
      value = (int32_t)(other * (1 << fracbits)); 
      return *this;
    }

    fixed& operator=(const int& other)
    {
      value = other << fracbits; 
      return *this;
    }

    bool operator==(const fixed& other) const
    { return value == other.value; }

    bool operator!=(const fixed& other) const
    { return value != other.value; }

    bool operator<(const fixed& other) const
    { return value < other.value; }

    bool operator>(const fixed& other) const
    { return value > other.value; }

    bool operator<=(const fixed& other) const
    { return value <= other.value; }

    bool operator>=(const fixed& other) const
    { return value >= other.value; }

    float toFloat() const
    { return ((float)value)/(1<<fracbits); }
};

  template<int fracbits>
fixed<fracbits> operator/(const int& l, const fixed<fracbits>& r)
{
  return fixed<fracbits>(1)/r;
}

template<int fracbits>
fixed<fracbits> sin(const fixed<fracbits>& r)
{
  
}



#endif

